home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / src / gas-211 / gas / symbols.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  24.9 KB  |  1,050 lines

  1. /* symbols.c -symbol table-
  2.  
  3.    Copyright (C) 1987, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GAS, the GNU Assembler.
  6.  
  7.    GAS is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2, or (at your option)
  10.    any later version.
  11.  
  12.    GAS is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with GAS; see the file COPYING.  If not, write to
  19.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #define DEBUG
  22.  
  23. #include <ctype.h>
  24.  
  25. #include "as.h"
  26.  
  27. #include "obstack.h"        /* For "symbols.h" */
  28. #include "subsegs.h"
  29.  
  30. #ifndef WORKING_DOT_WORD
  31. extern int new_broken_words;
  32. #endif
  33.  
  34. /* symbol-name => struct symbol pointer */
  35. static struct hash_control *sy_hash;
  36.  
  37. /* Below are commented in "symbols.h". */
  38. symbolS *symbol_rootP;
  39. symbolS *symbol_lastP;
  40. symbolS abs_symbol;
  41.  
  42. symbolS *dot_text_symbol;
  43. symbolS *dot_data_symbol;
  44. symbolS *dot_bss_symbol;
  45.  
  46. struct obstack notes;
  47.  
  48. static void fb_label_init PARAMS ((void));
  49.  
  50. void
  51. symbol_begin ()
  52. {
  53.   symbol_lastP = NULL;
  54.   symbol_rootP = NULL;        /* In case we have 0 symbols (!!) */
  55.   sy_hash = hash_new ();
  56.   memset ((char *) (&abs_symbol), '\0', sizeof (abs_symbol));
  57. #ifdef BFD_ASSEMBLER
  58.   abs_symbol.bsym = bfd_abs_section.symbol;
  59. #else
  60.   /* Can't initialise a union. Sigh. */
  61.   S_SET_SEGMENT (&abs_symbol, absolute_section);
  62. #endif
  63. #ifdef LOCAL_LABELS_FB
  64.   fb_label_init ();
  65. #endif /* LOCAL_LABELS_FB */
  66. }
  67.  
  68. /*
  69.  *            symbol_new()
  70.  *
  71.  * Return a pointer to a new symbol.
  72.  * Die if we can't make a new symbol.
  73.  * Fill in the symbol's values.
  74.  * Add symbol to end of symbol chain.
  75.  *
  76.  *
  77.  * Please always call this to create a new symbol.
  78.  *
  79.  * Changes since 1985: Symbol names may not contain '\0'. Sigh.
  80.  * 2nd argument is now a SEG rather than a TYPE.  The mapping between
  81.  * segments and types is mostly encapsulated herein (actually, we inherit it
  82.  * from macros in struc-symbol.h).
  83.  */
  84.  
  85. symbolS *
  86. symbol_new (name, segment, value, frag)
  87.      CONST char *name;        /* It is copied, the caller can destroy/modify */
  88.      segT segment;        /* Segment identifier (SEG_<something>) */
  89.      long value;        /* Symbol value */
  90.      fragS *frag;        /* Associated fragment */
  91. {
  92.   unsigned int name_length;
  93.   char *preserved_copy_of_name;
  94.   symbolS *symbolP;
  95.  
  96.   name_length = strlen (name) + 1;    /* +1 for \0 */
  97.   obstack_grow (¬es, name, name_length);
  98.   preserved_copy_of_name = obstack_finish (¬es);
  99. #ifdef STRIP_UNDERSCORE
  100.   if (preserved_copy_of_name[0] == '_')
  101.     preserved_copy_of_name++;
  102. #endif
  103.   symbolP = (symbolS *) obstack_alloc (¬es, sizeof (symbolS));
  104.  
  105.   /* symbol must be born in some fixed state.  This seems as good as any. */
  106.   memset (symbolP, 0, sizeof (symbolS));
  107.  
  108.  
  109. #ifdef BFD_ASSEMBLER
  110.   symbolP->bsym = bfd_make_empty_symbol (stdoutput);
  111.   assert (symbolP->bsym != 0);
  112. #endif
  113.   S_SET_NAME (symbolP, preserved_copy_of_name);
  114.  
  115.   S_SET_SEGMENT (symbolP, segment);
  116.   S_SET_VALUE (symbolP, value);
  117.   symbol_clear_list_pointers(symbolP);
  118.  
  119.   symbolP->sy_frag = frag;
  120.   symbolP->sy_forward = NULL;
  121. #ifndef BFD_ASSEMBLER
  122.   symbolP->sy_number = ~0;
  123.   symbolP->sy_name_offset = ~0;
  124. #endif
  125.  
  126.   /*
  127.    * Link to end of symbol chain.
  128.    */
  129.   symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
  130.  
  131.   obj_symbol_new_hook (symbolP);
  132.  
  133. #ifdef DEBUG
  134.   verify_symbol_chain(symbol_rootP, symbol_lastP);
  135. #endif /* DEBUG */
  136.  
  137.   return symbolP;
  138. }
  139.  
  140.  
  141. /*
  142.  *            colon()
  143.  *
  144.  * We have just seen "<name>:".
  145.  * Creates a struct symbol unless it already exists.
  146.  *
  147.  * Gripes if we are redefining a symbol incompatibly (and ignores it).
  148.  *
  149.  */
  150. void 
  151. colon (sym_name)        /* just seen "x:" - rattle symbols & frags */
  152.      register char *sym_name;    /* symbol name, as a cannonical string */
  153.      /* We copy this string: OK to alter later. */
  154. {
  155.   register symbolS *symbolP;    /* symbol we are working with */
  156.  
  157. #ifdef LOCAL_LABELS_DOLLAR
  158.   /* Sun local labels go out of scope whenever a non-local symbol is
  159.      defined.  */
  160.  
  161.   if (*sym_name != 'L')
  162.     dollar_label_clear ();
  163. #endif /* LOCAL_LABELS_DOLLAR */
  164.  
  165. #ifndef WORKING_DOT_WORD
  166.   if (new_broken_words)
  167.     {
  168.       struct broken_word *a;
  169.       int possible_bytes;
  170.       fragS *frag_tmp;
  171.       char *frag_opcode;
  172.  
  173.       extern const int md_short_jump_size;
  174.       extern const int md_long_jump_size;
  175.       possible_bytes = (md_short_jump_size
  176.             + new_broken_words * md_long_jump_size);
  177.  
  178.       frag_tmp = frag_now;
  179.       frag_opcode = frag_var (rs_broken_word,
  180.                   possible_bytes,
  181.                   possible_bytes,
  182.                   (relax_substateT) 0,
  183.                   (symbolS *) broken_words,
  184.                   0L,
  185.                   NULL);
  186.  
  187.       /* We want to store the pointer to where to insert the jump table in the
  188.      fr_opcode of the rs_broken_word frag.  This requires a little
  189.      hackery.  */
  190.       while (frag_tmp
  191.          && (frag_tmp->fr_type != rs_broken_word
  192.          || frag_tmp->fr_opcode))
  193.     frag_tmp = frag_tmp->fr_next;
  194.       know (frag_tmp);
  195.       frag_tmp->fr_opcode = frag_opcode;
  196.       new_broken_words = 0;
  197.  
  198.       for (a = broken_words; a && a->dispfrag == 0; a = a->next_broken_word)
  199.     a->dispfrag = frag_tmp;
  200.     }
  201. #endif /* WORKING_DOT_WORD */
  202.  
  203.   if ((symbolP = symbol_find (sym_name)) != 0)
  204.     {
  205. #ifdef RESOLVE_SYMBOL_REDEFINITION
  206.       if (RESOLVE_SYMBOL_REDEFINITION (symbolP))
  207.     return;
  208. #endif
  209.       /*
  210.        *    Now check for undefined symbols
  211.        */
  212.       if (!S_IS_DEFINED (symbolP))
  213.     {
  214.       if (S_GET_VALUE (symbolP) == 0)
  215.         {
  216.           symbolP->sy_frag = frag_now;
  217. #ifdef OBJ_VMS
  218.           S_GET_OTHER(symbolP) = const_flag;
  219. #endif
  220.           S_SET_VALUE (symbolP, obstack_next_free (&frags) - frag_now->fr_literal);
  221.           S_SET_SEGMENT (symbolP, now_seg);
  222. #ifdef N_UNDF
  223.           know (N_UNDF == 0);
  224. #endif /* if we have one, it better be zero. */
  225.  
  226.         }
  227.       else
  228.         {
  229.           /*
  230.            *    There are still several cases to check:
  231.            *        A .comm/.lcomm symbol being redefined as
  232.            *            initialized data is OK
  233.            *        A .comm/.lcomm symbol being redefined with
  234.            *            a larger size is also OK
  235.            *
  236.            * This only used to be allowed on VMS gas, but Sun cc
  237.            * on the sparc also depends on it.
  238.            */
  239.  
  240.           if (((!S_IS_DEBUG (symbolP)
  241.             && !S_IS_DEFINED (symbolP)
  242.             && S_IS_EXTERNAL (symbolP))
  243.            || S_GET_SEGMENT (symbolP) == bss_section)
  244.           && (now_seg == data_section
  245.               || now_seg == S_GET_SEGMENT (symbolP)))
  246.         {
  247.           /*
  248.            *    Select which of the 2 cases this is
  249.            */
  250.           if (now_seg != data_section)
  251.             {
  252.               /*
  253.                *   New .comm for prev .comm symbol.
  254.                *    If the new size is larger we just
  255.                *    change its value.  If the new size
  256.                *    is smaller, we ignore this symbol
  257.                */
  258.               if (S_GET_VALUE (symbolP)
  259.               < ((unsigned) frag_now_fix ()))
  260.             {
  261.               S_SET_VALUE (symbolP, frag_now_fix ());
  262.             }
  263.             }
  264.           else
  265.             {
  266.               /* It is a .comm/.lcomm being converted to initialized
  267.              data.  */
  268.               symbolP->sy_frag = frag_now;
  269. #ifdef OBJ_VMS
  270.               S_GET_OTHER(symbolP) = const_flag;
  271. #endif /* OBJ_VMS */
  272.               S_SET_VALUE (symbolP, frag_now_fix ());
  273.               S_SET_SEGMENT (symbolP, now_seg);    /* keep N_EXT bit */
  274.             }
  275.         }
  276.           else
  277.         {
  278. #if defined (S_GET_OTHER) && defined (S_GET_DESC)
  279.           as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.%d.%d.",
  280.                 sym_name,
  281.                 segment_name (S_GET_SEGMENT (symbolP)),
  282.                 S_GET_OTHER (symbolP), S_GET_DESC (symbolP),
  283.                 S_GET_VALUE (symbolP));
  284. #else
  285.           as_fatal ("Symbol \"%s\" is already defined as \"%s\"/%d.",
  286.                 sym_name,
  287.                 segment_name (S_GET_SEGMENT (symbolP)),
  288.                 S_GET_VALUE (symbolP));
  289. #endif
  290.         }
  291.         }            /* if the undefined symbol has no value */
  292.     }
  293.       else
  294.     {
  295.       /* Don't blow up if the definition is the same */
  296.       if (!(frag_now == symbolP->sy_frag
  297.         && S_GET_VALUE (symbolP) == obstack_next_free (&frags) - frag_now->fr_literal
  298.         && S_GET_SEGMENT (symbolP) == now_seg))
  299.         as_fatal ("Symbol %s already defined.", sym_name);
  300.     }            /* if this symbol is not yet defined */
  301.  
  302.     }
  303.   else
  304.     {
  305.       symbolP = symbol_new (sym_name,
  306.                 now_seg,
  307.            (valueT) (obstack_next_free (&frags) - frag_now->fr_literal),
  308.                 frag_now);
  309. #ifdef OBJ_VMS
  310.       S_SET_OTHER (symbolP, const_flag);
  311. #endif /* OBJ_VMS */
  312.  
  313.       symbol_table_insert (symbolP);
  314.     }                /* if we have seen this symbol before */
  315.  
  316.   return;
  317. }                /* colon() */
  318.  
  319.  
  320. /*
  321.  *            symbol_table_insert()
  322.  *
  323.  * Die if we can't insert the symbol.
  324.  *
  325.  */
  326.  
  327. void 
  328. symbol_table_insert (symbolP)
  329.      symbolS *symbolP;
  330. {
  331.   register char *error_string;
  332.  
  333.   know (symbolP);
  334.   know (S_GET_NAME (symbolP));
  335.  
  336.   if (*(error_string = hash_jam (sy_hash, S_GET_NAME (symbolP), (char *) symbolP)))
  337.     {
  338.       as_fatal ("Inserting \"%s\" into symbol table failed: %s",
  339.         S_GET_NAME (symbolP), error_string);
  340.     }                /* on error */
  341. }                /* symbol_table_insert() */
  342.  
  343. /*
  344.  *            symbol_find_or_make()
  345.  *
  346.  * If a symbol name does not exist, create it as undefined, and insert
  347.  * it into the symbol table. Return a pointer to it.
  348.  */
  349. symbolS *
  350. symbol_find_or_make (name)
  351.      char *name;
  352. {
  353.   register symbolS *symbolP;
  354.  
  355.   symbolP = symbol_find (name);
  356.  
  357.   if (symbolP == NULL)
  358.     {
  359.       symbolP = symbol_make (name);
  360.  
  361.       symbol_table_insert (symbolP);
  362.     }                /* if symbol wasn't found */
  363.  
  364.   return (symbolP);
  365. }                /* symbol_find_or_make() */
  366.  
  367. symbolS *
  368. symbol_make (name)
  369.      CONST char *name;
  370. {
  371.   symbolS *symbolP;
  372.  
  373.   /* Let the machine description default it, e.g. for register names. */
  374.   symbolP = md_undefined_symbol ((char *) name);
  375.  
  376.   if (!symbolP)
  377.     symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
  378.  
  379.   return (symbolP);
  380. }                /* symbol_make() */
  381.  
  382. /*
  383.  *            symbol_find()
  384.  *
  385.  * Implement symbol table lookup.
  386.  * In:    A symbol's name as a string: '\0' can't be part of a symbol name.
  387.  * Out:    NULL if the name was not in the symbol table, else the address
  388.  *    of a struct symbol associated with that name.
  389.  */
  390.  
  391. symbolS *
  392. symbol_find (name)
  393.      CONST char *name;
  394. {
  395. #ifdef STRIP_UNDERSCORE
  396.   return (symbol_find_base (name, 1));
  397. #else /* STRIP_UNDERSCORE */
  398.   return (symbol_find_base (name, 0));
  399. #endif /* STRIP_UNDERSCORE */
  400. }                /* symbol_find() */
  401.  
  402. symbolS *
  403. symbol_find_base (name, strip_underscore)
  404.      CONST char *name;
  405.      int strip_underscore;
  406. {
  407.   if (strip_underscore && *name == '_')
  408.     name++;
  409.   return ((symbolS *) hash_find (sy_hash, name));
  410. }
  411.  
  412. /*
  413.  * Once upon a time, symbols were kept in a singly linked list.  At
  414.  * least coff needs to be able to rearrange them from time to time, for
  415.  * which a doubly linked list is much more convenient.  Loic did these
  416.  * as macros which seemed dangerous to me so they're now functions.
  417.  * xoxorich.
  418.  */
  419.  
  420. /* Link symbol ADDME after symbol TARGET in the chain. */
  421. void 
  422. symbol_append (addme, target, rootPP, lastPP)
  423.      symbolS *addme;
  424.      symbolS *target;
  425.      symbolS **rootPP;
  426.      symbolS **lastPP;
  427. {
  428.   if (target == NULL)
  429.     {
  430.       know (*rootPP == NULL);
  431.       know (*lastPP == NULL);
  432.       *rootPP = addme;
  433.       *lastPP = addme;
  434.       return;
  435.     }                /* if the list is empty */
  436.  
  437.   if (target->sy_next != NULL)
  438.     {
  439. #ifdef SYMBOLS_NEED_BACKPOINTERS
  440.       target->sy_next->sy_previous = addme;
  441. #endif /* SYMBOLS_NEED_BACKPOINTERS */
  442.     }
  443.   else
  444.     {
  445.       know (*lastPP == target);
  446.       *lastPP = addme;
  447.     }                /* if we have a next */
  448.  
  449.   addme->sy_next = target->sy_next;
  450.   target->sy_next = addme;
  451.  
  452. #ifdef SYMBOLS_NEED_BACKPOINTERS
  453.   addme->sy_previous = target;
  454. #endif /* SYMBOLS_NEED_BACKPOINTERS */
  455. }
  456.  
  457. #ifdef SYMBOLS_NEED_BACKPOINTERS
  458. /* Remove SYMBOLP from the list. */
  459. void 
  460. symbol_remove (symbolP, rootPP, lastPP)
  461.      symbolS *symbolP;
  462.      symbolS **rootPP;
  463.      symbolS **lastPP;
  464. {
  465.   if (symbolP == *rootPP)
  466.     {
  467.       *rootPP = symbolP->sy_next;
  468.     }                /* if it was the root */
  469.  
  470.   if (symbolP == *lastPP)
  471.     {
  472.       *lastPP = symbolP->sy_previous;
  473.     }                /* if it was the tail */
  474.  
  475.   if (symbolP->sy_next != NULL)
  476.     {
  477.       symbolP->sy_next->sy_previous = symbolP->sy_previous;
  478.     }                /* if not last */
  479.  
  480.   if (symbolP->sy_previous != NULL)
  481.     {
  482.       symbolP->sy_previous->sy_next = symbolP->sy_next;
  483.     }                /* if not first */
  484.  
  485. #ifdef DEBUG
  486.   verify_symbol_chain (*rootPP, *lastPP);
  487. #endif /* DEBUG */
  488. }
  489.  
  490. /* Set the chain pointers of SYMBOL to null. */
  491. void 
  492. symbol_clear_list_pointers (symbolP)
  493.      symbolS *symbolP;
  494. {
  495.   symbolP->sy_next = NULL;
  496.   symbolP->sy_previous = NULL;
  497. }
  498.  
  499. /* Link symbol ADDME before symbol TARGET in the chain. */
  500. void 
  501. symbol_insert (addme, target, rootPP, lastPP)
  502.      symbolS *addme;
  503.      symbolS *target;
  504.      symbolS **rootPP;
  505.      symbolS **lastPP;
  506. {
  507.   if (target->sy_previous != NULL)
  508.     {
  509.       target->sy_previous->sy_next = addme;
  510.     }
  511.   else
  512.     {
  513.       know (*rootPP == target);
  514.       *rootPP = addme;
  515.     }                /* if not first */
  516.  
  517.   addme->sy_previous = target->sy_previous;
  518.   target->sy_previous = addme;
  519.   addme->sy_next = target;
  520.  
  521. #ifdef DEBUG
  522.   verify_symbol_chain (*rootPP, *lastPP);
  523. #endif /* DEBUG */
  524. }
  525.  
  526. #endif /* SYMBOLS_NEED_BACKPOINTERS */
  527.  
  528. void 
  529. verify_symbol_chain (rootP, lastP)
  530.      symbolS *rootP;
  531.      symbolS *lastP;
  532. {
  533.   symbolS *symbolP = rootP;
  534.  
  535.   if (symbolP == NULL)
  536.     return;
  537.  
  538.   for (; symbol_next (symbolP) != NULL; symbolP = symbol_next (symbolP))
  539.     {
  540. #ifdef SYMBOLS_NEED_BACKPOINTERS
  541.       know (symbolP->sy_next->sy_previous == symbolP);
  542. #else
  543.       /* Walk the list anyways, to make sure pointers are still good.  */
  544.       *symbolP;
  545. #endif /* SYMBOLS_NEED_BACKPOINTERS */
  546.     }
  547.  
  548.   assert (lastP == symbolP);
  549. }
  550.  
  551. void
  552. verify_symbol_chain_2 (sym)
  553.      symbolS *sym;
  554. {
  555.   symbolS *p = sym, *n = sym;
  556. #ifdef SYMBOLS_NEED_BACKPOINTERS
  557.   while (symbol_previous (p))
  558.     p = symbol_previous (p);
  559. #endif
  560.   while (symbol_next (n))
  561.     n = symbol_next (n);
  562.   verify_symbol_chain (p, n);
  563. }
  564.  
  565. #ifdef LOCAL_LABELS_DOLLAR
  566.  
  567. /* Dollar labels look like a number followed by a dollar sign.  Eg, "42$".
  568.    They are *really* local.  That is, they go out of scope whenever we see a
  569.    label that isn't local.  Also, like fb labels, there can be multiple
  570.    instances of a dollar label.  Therefor, we name encode each instance with
  571.    the instance number, keep a list of defined symbols separate from the real
  572.    symbol table, and we treat these buggers as a sparse array.  */
  573.  
  574. static long *dollar_labels;
  575. static long *dollar_label_instances;
  576. static char *dollar_label_defines;
  577. static long dollar_label_count;
  578. static long dollar_label_max;
  579.  
  580. int 
  581. dollar_label_defined (label)
  582.      long label;
  583. {
  584.   long *i;
  585.  
  586.   know ((dollar_labels != NULL) || (dollar_label_count == 0));
  587.  
  588.   for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
  589.     if (*i == label)
  590.       return dollar_label_defines[i - dollar_labels];
  591.  
  592.   /* if we get here, label isn't defined */
  593.   return 0;
  594. }                /* dollar_label_defined() */
  595.  
  596. static int 
  597. dollar_label_instance (label)
  598.      long label;
  599. {
  600.   long *i;
  601.  
  602.   know ((dollar_labels != NULL) || (dollar_label_count == 0));
  603.  
  604.   for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
  605.     if (*i == label)
  606.       return (dollar_label_instances[i - dollar_labels]);
  607.  
  608.   /* If we get here, we haven't seen the label before, therefore its instance
  609.      count is zero.  */
  610.   return 0;
  611. }
  612.  
  613. void 
  614. dollar_label_clear ()
  615. {
  616.   memset (dollar_label_defines, '\0', dollar_label_count);
  617. }
  618.  
  619. #define DOLLAR_LABEL_BUMP_BY 10
  620.  
  621. void 
  622. define_dollar_label (label)
  623.      long label;
  624. {
  625.   long *i;
  626.  
  627.   for (i = dollar_labels; i < dollar_labels + dollar_label_count; ++i)
  628.     if (*i == label)
  629.       {
  630.     ++dollar_label_instances[i - dollar_labels];
  631.     dollar_label_defines[i - dollar_labels] = 1;
  632.     return;
  633.       }
  634.  
  635.   /* if we get to here, we don't have label listed yet. */
  636.  
  637.   if (dollar_labels == NULL)
  638.     {
  639.       dollar_labels = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
  640.       dollar_label_instances = (long *) xmalloc (DOLLAR_LABEL_BUMP_BY * sizeof (long));
  641.       dollar_label_defines = xmalloc (DOLLAR_LABEL_BUMP_BY);
  642.       dollar_label_max = DOLLAR_LABEL_BUMP_BY;
  643.       dollar_label_count = 0;
  644.     }
  645.   else if (dollar_label_count == dollar_label_max)
  646.     {
  647.       dollar_label_max += DOLLAR_LABEL_BUMP_BY;
  648.       dollar_labels = (long *) xrealloc ((char *) dollar_labels,
  649.                      dollar_label_max * sizeof (long));
  650.       dollar_label_instances = (long *) xrealloc ((char *) dollar_label_instances,
  651.                       dollar_label_max * sizeof (long));
  652.       dollar_label_defines = xrealloc (dollar_label_defines, dollar_label_max);
  653.     }                /* if we needed to grow */
  654.  
  655.   dollar_labels[dollar_label_count] = label;
  656.   dollar_label_instances[dollar_label_count] = 1;
  657.   dollar_label_defines[dollar_label_count] = 1;
  658.   ++dollar_label_count;
  659. }
  660.  
  661. /*
  662.  *            dollar_label_name()
  663.  *
  664.  * Caller must copy returned name: we re-use the area for the next name.
  665.  *
  666.  * The mth occurence of label n: is turned into the symbol "Ln^Am" where
  667.  * n is the label number and m is the instance number. "L" makes it a label discarded
  668.  * unless debugging and "^A"('\1') ensures no ordinary symbol SHOULD get the
  669.  * same name as a local label symbol. The first "4:" is "L4^A1" - the m
  670.  * numbers begin at 1.
  671.  *
  672.  * fb labels get the same treatment, except that ^B is used in place of ^A.
  673.  */
  674.  
  675. char *                /* Return local label name. */
  676. dollar_label_name (n, augend)
  677.      register long n;        /* we just saw "n$:" : n a number */
  678.      register int augend;    /* 0 for current instance, 1 for new instance */
  679. {
  680.   long i;
  681.   /* Returned to caller, then copied.  used for created names ("4f") */
  682.   static char symbol_name_build[24];
  683.   register char *p;
  684.   register char *q;
  685.   char symbol_name_temporary[20];    /* build up a number, BACKWARDS */
  686.  
  687.   know (n >= 0);
  688.   know (augend == 0 || augend == 1);
  689.   p = symbol_name_build;
  690.   *p++ = 'L';
  691.  
  692.   /* Next code just does sprintf( {}, "%d", n); */
  693.   /* label number */
  694.   q = symbol_name_temporary;
  695.   for (*q++ = 0, i = n; i; ++q)
  696.     {
  697.       *q = i % 10 + '0';
  698.       i /= 10;
  699.     }
  700.   while ((*p = *--q) != '\0')
  701.     ++p;
  702.  
  703.   *p++ = 1;            /* ^A */
  704.  
  705.   /* instance number */
  706.   q = symbol_name_temporary;
  707.   for (*q++ = 0, i = dollar_label_instance (n) + augend; i; ++q)
  708.     {
  709.       *q = i % 10 + '0';
  710.       i /= 10;
  711.     }
  712.   while ((*p++ = *--q) != '\0');;
  713.  
  714.   /* The label, as a '\0' ended string, starts at symbol_name_build. */
  715.   return symbol_name_build;
  716. }
  717.  
  718. #endif /* LOCAL_LABELS_DOLLAR */
  719.  
  720. #ifdef LOCAL_LABELS_FB
  721.  
  722. /*
  723.  * Sombody else's idea of local labels. They are made by "n:" where n
  724.  * is any decimal digit. Refer to them with
  725.  *  "nb" for previous (backward) n:
  726.  *  or "nf" for next (forward) n:.
  727.  *
  728.  * We do a little better and let n be any number, not just a single digit, but
  729.  * since the other guy's assembler only does ten, we treat the first ten
  730.  * specially.
  731.  *
  732.  * Like someone else's assembler, we have one set of local label counters for
  733.  * entire assembly, not one set per (sub)segment like in most assemblers. This
  734.  * implies that one can refer to a label in another segment, and indeed some
  735.  * crufty compilers have done just that.
  736.  *
  737.  * Since there could be a LOT of these things, treat them as a sparse array.
  738.  */
  739.  
  740. #define FB_LABEL_SPECIAL (10)
  741.  
  742. static long fb_low_counter[FB_LABEL_SPECIAL];
  743. static long *fb_labels;
  744. static long *fb_label_instances;
  745. static long fb_label_count = 0;
  746. static long fb_label_max = 0;
  747.  
  748. /* this must be more than FB_LABEL_SPECIAL */
  749. #define FB_LABEL_BUMP_BY (FB_LABEL_SPECIAL + 6)
  750.  
  751. static void 
  752. fb_label_init ()
  753. {
  754.   memset ((void *) fb_low_counter, '\0', sizeof (fb_low_counter));
  755. }                /* fb_label_init() */
  756.  
  757. /* add one to the instance number of this fb label */
  758. void 
  759. fb_label_instance_inc (label)
  760.      long label;
  761. {
  762.   long *i;
  763.  
  764.   if (label < FB_LABEL_SPECIAL)
  765.     {
  766.       ++fb_low_counter[label];
  767.       return;
  768.     }
  769.  
  770.   for (i = fb_labels + FB_LABEL_SPECIAL; i < fb_labels + fb_label_count; ++i)
  771.     {
  772.       if (*i == label)
  773.     {
  774.       ++fb_label_instances[i - fb_labels];
  775.       return;
  776.     }            /* if we find it */
  777.     }                /* for each existing label */
  778.  
  779.   /* if we get to here, we don't have label listed yet. */
  780.  
  781.   if (fb_labels == NULL)
  782.     {
  783.       fb_labels = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
  784.       fb_label_instances = (long *) xmalloc (FB_LABEL_BUMP_BY * sizeof (long));
  785.       fb_label_max = FB_LABEL_BUMP_BY;
  786.       fb_label_count = FB_LABEL_SPECIAL;
  787.  
  788.     }
  789.   else if (fb_label_count == fb_label_max)
  790.     {
  791.       fb_label_max += FB_LABEL_BUMP_BY;
  792.       fb_labels = (long *) xrealloc ((char *) fb_labels,
  793.                      fb_label_max * sizeof (long));
  794.       fb_label_instances = (long *) xrealloc ((char *) fb_label_instances,
  795.                           fb_label_max * sizeof (long));
  796.     }                /* if we needed to grow */
  797.  
  798.   fb_labels[fb_label_count] = label;
  799.   fb_label_instances[fb_label_count] = 1;
  800.   ++fb_label_count;
  801.   return;
  802. }                /* fb_label_instance_inc() */
  803.  
  804. static long 
  805. fb_label_instance (label)
  806.      long label;
  807. {
  808.   long *i;
  809.  
  810.   if (label < FB_LABEL_SPECIAL)
  811.     {
  812.       return (fb_low_counter[label]);
  813.     }
  814.  
  815.   for (i = fb_labels + FB_LABEL_SPECIAL; i < fb_labels + fb_label_count; ++i)
  816.     {
  817.       if (*i == label)
  818.     {
  819.       return (fb_label_instances[i - fb_labels]);
  820.     }            /* if we find it */
  821.     }                /* for each existing label */
  822.  
  823.   /* NOTREACHED */
  824.   abort ();
  825. }
  826.  
  827. /*
  828.  *            fb_label_name()
  829.  *
  830.  * Caller must copy returned name: we re-use the area for the next name.
  831.  *
  832.  * The mth occurence of label n: is turned into the symbol "Ln^Bm" where
  833.  * n is the label number and m is the instance number. "L" makes it a label discarded
  834.  * unless debugging and "^B"('\2') ensures no ordinary symbol SHOULD get the
  835.  * same name as a local label symbol. The first "4:" is "L4^B1" - the m
  836.  * numbers begin at 1.
  837.  *
  838.  * dollar labels get the same treatment, except that ^A is used in place of ^B.
  839.  */
  840.  
  841. char *                /* Return local label name. */
  842. fb_label_name (n, augend)
  843.      long n;            /* we just saw "n:", "nf" or "nb" : n a number */
  844.      long augend;        /* 0 for nb, 1 for n:, nf */
  845. {
  846.   long i;
  847.   /* Returned to caller, then copied.  used for created names ("4f") */
  848.   static char symbol_name_build[24];
  849.   register char *p;
  850.   register char *q;
  851.   char symbol_name_temporary[20];    /* build up a number, BACKWARDS */
  852.  
  853.   know (n >= 0);
  854.   know (augend == 0 || augend == 1);
  855.   p = symbol_name_build;
  856.   *p++ = 'L';
  857.  
  858.   /* Next code just does sprintf( {}, "%d", n); */
  859.   /* label number */
  860.   q = symbol_name_temporary;
  861.   for (*q++ = 0, i = n; i; ++q)
  862.     {
  863.       *q = i % 10 + '0';
  864.       i /= 10;
  865.     }
  866.   while ((*p = *--q) != '\0')
  867.     ++p;
  868.  
  869.   *p++ = 2;            /* ^B */
  870.  
  871.   /* instance number */
  872.   q = symbol_name_temporary;
  873.   for (*q++ = 0, i = fb_label_instance (n) + augend; i; ++q)
  874.     {
  875.       *q = i % 10 + '0';
  876.       i /= 10;
  877.     }
  878.   while ((*p++ = *--q) != '\0');;
  879.  
  880.   /* The label, as a '\0' ended string, starts at symbol_name_build. */
  881.   return (symbol_name_build);
  882. }                /* fb_label_name() */
  883.  
  884. #endif /* LOCAL_LABELS_FB */
  885.  
  886.  
  887. /*
  888.  * decode name that may have been generated by foo_label_name() above.  If
  889.  * the name wasn't generated by foo_label_name(), then return it unaltered.
  890.  * This is used for error messages.
  891.  */
  892.  
  893. char *
  894. decode_local_label_name (s)
  895.      char *s;
  896. {
  897.   char *p;
  898.   char *symbol_decode;
  899.   int label_number;
  900.   int instance_number;
  901.   char *type;
  902.   const char *message_format = "\"%d\" (instance number %d of a %s label)";
  903.  
  904.   if (s[0] != 'L')
  905.     return (s);
  906.  
  907.   for (label_number = 0, p = s + 1; isdigit (*p); ++p)
  908.     {
  909.       label_number = (10 * label_number) + *p - '0';
  910.     }
  911.  
  912.   if (*p == 1)
  913.     {
  914.       type = "dollar";
  915.     }
  916.   else if (*p == 2)
  917.     {
  918.       type = "fb";
  919.     }
  920.   else
  921.     {
  922.       return (s);
  923.     }
  924.  
  925.   for (instance_number = 0, p = s + 1; isdigit (*p); ++p)
  926.     {
  927.       instance_number = (10 * instance_number) + *p - '0';
  928.     }
  929.  
  930.   symbol_decode = obstack_alloc (¬es, strlen (message_format) + 30);
  931.   (void) sprintf (symbol_decode, message_format, label_number,
  932.           instance_number, type);
  933.  
  934.   return (symbol_decode);
  935. }                /* decode_local_label_name() */
  936.  
  937. #ifdef BFD_ASSEMBLER
  938.  
  939. S_IS_EXTERNAL (s)
  940.      symbolS *s;
  941. {
  942.   if (s->bsym->flags & BSF_EXPORT)
  943.     return 1;
  944.   return 0;
  945. }
  946.  
  947. S_IS_COMMON (s)
  948.      symbolS *s;
  949. {
  950.   return s->bsym->section == &bfd_com_section;
  951. }
  952.  
  953. S_IS_DEFINED (s)
  954.      symbolS *s;
  955. {
  956.   return s->bsym->section != undefined_section;
  957. }
  958.  
  959. S_IS_DEBUG (s)
  960.      symbolS *s;
  961. {
  962.   if (s->bsym->flags & BSF_DEBUGGING)
  963.     return 1;
  964.   return 0;
  965. }
  966.  
  967. S_IS_LOCAL (s)
  968.      symbolS *s;
  969. {
  970.   return (S_GET_NAME (s)
  971.       && ! S_IS_DEBUG (s)
  972.       && (strchr (S_GET_NAME (s), '\001')
  973.           || strchr (S_GET_NAME (s), '\002')
  974.           || (S_LOCAL_NAME (s)
  975.           && !flagseen['L'])));
  976. }
  977.  
  978. S_IS_EXTERN (s)
  979.      symbolS *s;
  980. {
  981.   return S_IS_EXTERNAL (s);
  982. }
  983.  
  984. S_IS_STABD (s)
  985.      symbolS *s;
  986. {
  987.   return S_GET_NAME (s) == 0;
  988. }
  989.  
  990. S_GET_VALUE (s)
  991.      symbolS *s;
  992. {
  993.   return s->bsym->value;
  994. }
  995.  
  996. CONST char *
  997. S_GET_NAME (s)
  998.      symbolS *s;
  999. {
  1000.   return s->bsym->name;
  1001. }
  1002.  
  1003. segT
  1004. S_GET_SEGMENT (s)
  1005.      symbolS *s;
  1006. {
  1007.   return s->bsym->section;
  1008. }
  1009.  
  1010. void
  1011. S_SET_VALUE (s, val)
  1012.      symbolS *s;
  1013.      long val;
  1014. {
  1015.   s->bsym->value = val;
  1016. }
  1017.  
  1018. void
  1019. S_SET_SEGMENT (s, seg)
  1020.      symbolS *s;
  1021.      segT seg;
  1022. {
  1023.   s->bsym->section = seg;
  1024. }
  1025.  
  1026. void
  1027. S_SET_EXTERNAL (s)
  1028.      symbolS *s;
  1029. {
  1030.   s->bsym->flags |= BSF_EXPORT;
  1031. }
  1032.  
  1033. void
  1034. S_CLEAR_EXTERNAL (s)
  1035.      symbolS *s;
  1036. {
  1037.   s->bsym->flags &= ~BSF_EXPORT;
  1038. }
  1039.  
  1040. void
  1041. S_SET_NAME (s, name)
  1042.      symbolS *s;
  1043.      char *name;
  1044. {
  1045.   s->bsym->name = name;
  1046. }
  1047. #endif /* BFD_ASSEMBLER */
  1048.  
  1049. /* end of symbols.c */
  1050.